#pragma once

#include <istream>
#include <ostream>

namespace MiniHttpServer
{
	private ref class InputStreamWrapper : public System::IO::Stream
	{
	public:
		InputStreamWrapper(std::istream& stream)
			: m_stream(stream)
		{
		}

		virtual property bool CanRead  { bool get() override { return true; }; };
		virtual property bool CanWrite { bool get() override { return false; }; };
		virtual property bool CanSeek  { bool get() override { return false; }; };

		virtual int Read (array<unsigned char>^ buffer, int offset, int count) override 
		{
			pin_ptr<unsigned char> pBuffer(&buffer[0]);
			m_stream.read(reinterpret_cast<char*>(pBuffer)+offset, count);
			return static_cast<int>(m_stream.gcount());
		}

		virtual void Write (array<unsigned char>^ buffer, int offset, int count) override { return; }
		virtual property __int64 Length { __int64 get() override { return 0; }; };
		virtual property __int64 Position
		{ 
			__int64 get() override { return m_stream.tellg(); }; 
			void set(__int64) override { }; 
		};
		virtual __int64 Seek(__int64, System::IO::SeekOrigin) override { return 0; };
		virtual void SetLength(__int64) override { };
		virtual void Flush() override { };

	private:
		std::istream& m_stream;
	};

	private ref class OutputStreamWrapper : public System::IO::Stream
	{
	public:
		OutputStreamWrapper(std::ostream& stream)
			: m_stream(stream)
		{
		}

		virtual property bool CanRead  { bool get() override { return false; }; };
		virtual property bool CanWrite { bool get() override { return true; }; };
		virtual property bool CanSeek  { bool get() override { return false; }; };

		virtual int Read (array<unsigned char>^ buffer, int offset, int count) override { return 0; }

		virtual void Write (array<unsigned char>^ buffer, int offset, int count) override
		{
			pin_ptr<unsigned char> pBuffer(&buffer[0]);
			m_stream.write(reinterpret_cast<char*>(pBuffer)+offset, count);
		}
		virtual property __int64 Length 
		{ 
			__int64 get() override { return m_stream.tellp(); }; 
		};
		virtual property __int64 Position
		{ 
			__int64 get() override { return m_stream.tellp(); }; 
			void set(__int64) override { }; 
		};
		virtual __int64 Seek(__int64, System::IO::SeekOrigin) override { return 0; };
		virtual void SetLength(__int64) override { };
		virtual void Flush() override { m_stream.flush(); };

	private:
		std::ostream& m_stream;
	};
};
